<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <link rel="shortcut icon" href="../img/favicon.ico" type="image/x-icon">
  <link rel="stylesheet" href="../css/style.css">
  <title>虚拟DOM简介</title>
</head>
<body>
  <img src="../img/introduce-VNode.png" alt="">
  <h2>虚拟DOM简介</h2>
  <h3>什么是虚拟DOM</h3>
  <li>业务越来越复杂，如果利用原生或者JQ的DOM操作来更新DOM，会发现代码中有一半数量都是用来操作DOM</li>
  <li>
    而应用的开发重心应该是于业务的流程或者是状态的变化。不应该在大量的DOM操作上。Vuejs描述了一种从状态到DOM的映射关系。让我们能最大限度的减少DOM操作来简化开发。只需维护与DOM相关的状态，Vue.js会替我们把状态显示在视图上
  </li>
  <li>
    一般来说，状态变更后去更新DOM有两种思路，一种是删掉之前的，用最新的状态重新生成，不用关心哪个状态发生了变化，哪个没有。但是这种做法性能是及其不友好的（过多的操作DOM）
  </li>
  <li>
    另一种思路是我们需要找出来哪些状态发生了变化，<span>只更新与变化了的状态相关联的DOM节点。</span>虚拟DOM是实现这种方案的思路
  </li>
  <li>
    虚拟DOM的解决方式是通过状态生成一个节点树，当状态变化时，将<span>新的节点树</span>与<span>上一次的虚拟节点树</span>进行对比，只渲染不同的部分
  </li>

  <h3>为什么引入虚拟DOM</h3>
  <li>
    Vue.js的变化侦测是以状态为单元的(<span>Object.definedProperty</span>)。这就说明，当VueJS状态变化的时候，Vue能够知道哪些状态发生了变化。从而对使用了这个状态的节点(watcher)进行更新操作。
    根本不需要对比。那么为什么还要引入一个虚拟DOM，在虚拟DOM上进行对比呢？
  </li>
  <li>
    <b>Vue2.0把<span>组件级别</span>当作一个watcher实例。就是说，即便一个组件内有十个节点使用了某个状态，但其实也只有一个watcher在观察这个状态的变化。所以当状态变化时，<span>只能通知到组件</span>。然后<span>组件内部</span>通过虚拟DOM去进行对比与渲染</b>
  </li>

  <h3>Vuejs的虚拟DOM</h3>
  <li>
    Vue.js通过<span>编译</span>将模板转化为<span>渲染函数</span>,执行渲染函数就可以得到一个<span>虚拟节点树</span>,使用这个虚拟节点树就可以渲染页面
  </li>
  <li>
    虚拟DOM的终极目标是将虚拟节点渲染到视图上
  </li>
  <li>
    在Vnode渲染到视图前，为了避免不必要的DOM操作，Vuejs会将新旧虚拟节点做对比，找出真正需要更新的节点来进行DOM操作
  </li>
</body>
</html>